/*
 * Copyright 2008-2009 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.example.db.config;
import net.hasor.core.TypeSupplier;
import net.hasor.dataql.DimUdf;
import net.hasor.dataql.DimUdfSource;
import net.hasor.dataql.Finder;
import net.hasor.dataql.QueryApiBinder;
import net.hasor.dataway.dal.providers.db.InformationStorage;
import net.hasor.db.JdbcModule;
import net.hasor.db.Level;
import net.hasor.web.WebApiBinder;
import net.hasor.web.WebModule;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Map;
import java.util.Objects;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

/**
 * @author 赵永春 (zyc@hasor.net)
 * @version : 2021-01-02
 */
@Component
public class DatawayModule implements WebModule, TypeSupplier {
//    @Resource(name = "metadataDs")
//    private DataSource         metadataDs = null;
//    @Resource(name = "dataDs1")
//    private DataSource         dataDs1    = null;
//    @Resource(name = "dataDs2")
//    private DataSource         dataDs2    = null;
//    @Resource(name = "dataDs3")
//    private DataSource         dataDs3    =

    //指定主数据源，主数据源包含 dataway metetable的数据源
    @Value("${spring.datasource.dynamic.primary:master}")
    private String primaryDsName = "master";

    @Resource
    private ApplicationContext applicationContext;

    @Override
    public <T> T get(Class<? extends T> targetType) {
        return applicationContext.getBean(targetType);
    }

    @Override
    public <T> boolean test(Class<? extends T> targetType) {
        return applicationContext.getBeanNamesForType(targetType).length > 0;
    }

    @Override
    public void loadModule(WebApiBinder apiBinder) throws Throwable {
        apiBinder.setEncodingCharacter("UTF-8", "UTF-8");
//        WebApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(apiBinder.getServletContext());
        DynamicRoutingDataSource dynamicRoutingDataSource = (DynamicRoutingDataSource) applicationContext.getBean("dataSource");
        if (dynamicRoutingDataSource.getDataSource(primaryDsName)== null ) {
            System.out.println("dataway所需的数据源未指定，请指定。");
        } else {
            System.out.println("dataway所需的数据源已指定。");
        }
        this.getDruidDataSource(dynamicRoutingDataSource, apiBinder);//动态载入spring数据源

        //
        // .check dataSource
//        Objects.requireNonNull(this.metadataDs, "metadataDs is null");
//        Objects.requireNonNull(this.dataDs1, "dataDs1 is null");
//        Objects.requireNonNull(this.dataDs2, "dataDs2 is null");
//        Objects.requireNonNull(this.dataDs3, "dataDs2 is null");
//        //
//        // .isolation meta-tables using InformationStorage
//        apiBinder.bindType(InformationStorage.class).toInstance(() -> {
//            return this.metadataDs;
//        });
//        //
//        // .add two data sources in to Dataway
//        apiBinder.installModule(new JdbcModule(Level.Full, "ds1", this.dataDs1));
//        apiBinder.installModule(new JdbcModule(Level.Full, "ds2", this.dataDs2));
//        apiBinder.installModule(new JdbcModule(Level.Full, "ds3", this.dataDs3));
        //
        // udf/udfSource/import 指令 的类型创建委托给 spring
        QueryApiBinder queryBinder = apiBinder.tryCast(QueryApiBinder.class);
        queryBinder.bindFinder(Finder.TYPE_SUPPLIER.apply(this));

//        QueryApiBinder queryBinder = apiBinder.tryCast(QueryApiBinder.class);
//        queryBinder.bindFinder(Finder.TYPE_SUPPLIER.apply(springTypeSupplier(apiBinder)));
        queryBinder.loadUdf(queryBinder.findClass(DimUdf.class));
        queryBinder.loadUdfSource(queryBinder.findClass(DimUdfSource.class));
//        queryBinder.loadFragment(queryBinder.findClass(DimFragment.class));

        // spi`s
       /* apiBinder.bindSpiListener(LoginPerformChainSpi.class, AuthLoginPerformChainSpi.class);
        apiBinder.bindSpiListener(LoginTokenChainSpi.class, AuthLoginTokenChainSpi.class);
        apiBinder.bindSpiListener(AuthorizationChainSpi.class, AuthAuthorizationChainSpi.class);*/

        //绑定java bean
//        apiBinder.bindType(BeanBizc.class, this.BeanBizc);

        //绑定udfresource service bean
//        apiBinder.bindType(IudfService.class, iudfService);
    }


    /**
     * 动态载入spirng 数据源
     * @param dynamicRoutingDataSource
     * @param apiBinder
     */
    private void getDruidDataSource(DynamicRoutingDataSource dynamicRoutingDataSource, WebApiBinder apiBinder) {

        Map<String, DataSource> dts = dynamicRoutingDataSource.getCurrentDataSources();
        dts.forEach((k, v)->{
            //
            // .check dataSource
            Objects.requireNonNull(v, k +" is null");
            //
            if (primaryDsName.equals(k)) {
                // .isolation meta-tables using InformationStorage
                apiBinder.bindType(InformationStorage.class).toInstance(() -> {
                    return v;
                });
            }
            // .add two data sources in to Dataway
            try {
//                apiBinder.installModule(new JdbcModule(Level.Full, k.replace("DB","Ds"), v));
                apiBinder.installModule(new JdbcModule(Level.Full, k, v));
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
            System.out.printf("dataway已加载数据源{%1s}， 数据源信息：{%2s}\n", k, "");
        });
    }
}